{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "8da638ca",
   "metadata": {},
   "source": [
    "### In this notebook we perform individual training.\n",
    "In individual learning each base station has access only to it's private dataset."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "2f3d7d47",
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-08-17T12:16:16.551243Z",
     "end_time": "2023-08-17T12:16:16.628890Z"
    }
   },
   "outputs": [],
   "source": [
    "import sys\n",
    "import os\n",
    "\n",
    "from pathlib import Path\n",
    "\n",
    "parent = Path(os.path.abspath(\"\")).resolve().parents[0]\n",
    "if parent not in sys.path:\n",
    "    sys.path.insert(0, str(parent))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "01e170e2",
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-08-17T12:16:16.562244Z",
     "end_time": "2023-08-17T12:16:16.728316Z"
    }
   },
   "outputs": [],
   "source": [
    "import random\n",
    "\n",
    "import pandas as pd\n",
    "\n",
    "import numpy as np\n",
    "import torch\n",
    "\n",
    "from argparse import Namespace"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "15abc428",
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-08-17T12:16:16.576244Z",
     "end_time": "2023-08-17T12:16:16.734315Z"
    }
   },
   "outputs": [],
   "source": [
    "from ml.utils.data_utils import read_data, generate_time_lags, time_to_feature, handle_nans, to_Xy, \\\n",
    "    to_torch_dataset, to_timeseries_rep, assign_statistics, \\\n",
    "    to_train_val, scale_features, get_data_by_area, remove_identifiers, get_exogenous_data_by_area, handle_outliers"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "350c9d6f",
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-08-17T12:16:16.591860Z",
     "end_time": "2023-08-17T12:16:16.763313Z"
    }
   },
   "outputs": [],
   "source": [
    "from ml.utils.train_utils import train, test"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "4688fbec",
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-08-17T12:16:16.608868Z",
     "end_time": "2023-08-17T12:16:16.763313Z"
    }
   },
   "outputs": [],
   "source": [
    "from ml.models.mlp import MLP\n",
    "from ml.models.rnn import RNN\n",
    "from ml.models.lstm import LSTM\n",
    "from ml.models.gru import GRU\n",
    "from ml.models.cnn import CNN\n",
    "from ml.models.rnn_autoencoder import DualAttentionAutoEncoder"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "f3db1750",
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-08-17T12:16:16.625892Z",
     "end_time": "2023-08-17T12:16:16.764314Z"
    }
   },
   "outputs": [],
   "source": [
    "args = Namespace(\n",
    "    data_path='../mydatase/marketData/full_dataset.csv',  # dataset\n",
    "    data_path_test=['../mydatase/marketData/Stort1_test.csv'],  # test dataset 这里实际并没有用上\n",
    "    test_size=0.2,  # validation size\n",
    "    targets=['Weekly_Sales'],  # the target columns\n",
    "    num_lags=5,  # the number of past observations to feed as input\n",
    "    filter_bs=None,  # whether to use a single bs for training. It will be changed dynamically\n",
    "    identifier='District',  # the column name that identifies a bs\n",
    "    nan_constant=0,  # the constant to transform nan values\n",
    "    x_scaler='standard',  # x_scaler\n",
    "    y_scaler='standard',  # y_scaler\n",
    "    outlier_detection=None,  # whether to perform flooring and capping\n",
    "    criterion='mse',  # optimization criterion, mse or l1\n",
    "    epochs=150,  # the number of maximum epochs\n",
    "    lr=0.001,  # learning rate\n",
    "    optimizer='adam',  # the optimizer, it can be sgd or adam\n",
    "    batch_size=128,  # the batch size to use\n",
    "    early_stopping=True,  # whether to use early stopping\n",
    "    patience=50,  # patience value for the early stopping parameter (if specified)\n",
    "    max_grad_norm=0.0,  # whether to clip grad norm\n",
    "    reg1=0.0,  # l1 regularization\n",
    "    reg2=0.0,  # l2 regularization\n",
    "    plot_history=True,  # plot loss history\n",
    "    cuda=True,  # whether to use gpu\n",
    "    seed=0,  # reproducibility\n",
    "    assign_stats=None,\n",
    "    # whether to use statistics as exogenous data, [\"mean\", \"median\", \"std\", \"variance\", \"kurtosis\", \"skew\"]\n",
    "    use_time_features=False  # whether to use datetime features\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e56a743e",
   "metadata": {},
   "source": [
    "> You can define the base station to perform train on the filter_bs parameter and use it in block 12 or you can define the base station to block 12 explicitly "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "763c39ae",
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-08-17T12:16:16.639892Z",
     "end_time": "2023-08-17T12:16:16.764314Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Script arguments: Namespace(data_path='../mydatase/marketData/full_dataset.csv', data_path_test=['../mydatase/marketData/Stort1_test.csv'], test_size=0.2, targets=['Weekly_Sales'], num_lags=1, filter_bs=None, identifier='District', nan_constant=0, x_scaler='standard', y_scaler='standard', outlier_detection=None, criterion='mse', epochs=150, lr=0.001, optimizer='adam', batch_size=128, early_stopping=True, patience=50, max_grad_norm=0.0, reg1=0.0, reg2=0.0, plot_history=True, cuda=True, seed=0, assign_stats=None, use_time_features=False)\n",
      "\n"
     ]
    }
   ],
   "source": [
    "print(f\"Script arguments: {args}\\n\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "da3431ef",
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-08-17T12:16:16.656891Z",
     "end_time": "2023-08-17T12:16:16.764314Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Using cuda\n"
     ]
    }
   ],
   "source": [
    "device = \"cuda\" if args.cuda and torch.cuda.is_available() else \"cpu\"\n",
    "print(f\"Using {device}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "06bb4aaa",
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-08-17T12:16:16.671892Z",
     "end_time": "2023-08-17T12:16:16.764314Z"
    }
   },
   "outputs": [],
   "source": [
    "# Outlier detection specification\n",
    "# if args.outlier_detection is not None:\n",
    "#     outlier_columns = ['rb_down', 'rb_up', 'down', 'up']\n",
    "#     outlier_kwargs = {\"ElBorn\": (10, 90), \"LesCorts\": (10, 90), \"PobleSec\": (5, 95)}\n",
    "#     args.outlier_columns = outlier_columns\n",
    "#     args.outlier_kwargs = outlier_kwargs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "1ac1d35a",
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-08-17T12:16:16.686891Z",
     "end_time": "2023-08-17T12:16:16.764314Z"
    }
   },
   "outputs": [],
   "source": [
    "def seed_all():\n",
    "    # ensure reproducibility\n",
    "    random.seed(args.seed)\n",
    "    np.random.seed(args.seed)\n",
    "    torch.manual_seed(args.seed)\n",
    "    torch.cuda.manual_seed_all(args.seed)\n",
    "    torch.backends.cudnn.deterministic = True\n",
    "    torch.backends.cudnn.benchmark = False"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "ea3ddd05",
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-08-17T12:16:16.702891Z",
     "end_time": "2023-08-17T12:16:16.764314Z"
    }
   },
   "outputs": [],
   "source": [
    "seed_all()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "00543376",
   "metadata": {},
   "source": [
    "### The preprocessing pipeline performed here for the base station specified in filter_bs argument\n",
    "Preprocessing inlcudes:\n",
    "1. NaNs Handling\n",
    "2. Outliers Handling\n",
    "3. Scaling Data\n",
    "4. Generating time lags\n",
    "5. Generating and importing exogenous data as features (time, statistics) (if applied)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "35bc6b48",
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-08-17T12:16:16.724314Z",
     "end_time": "2023-08-17T12:16:16.764314Z"
    }
   },
   "outputs": [],
   "source": [
    "def make_preprocessing(filter_bs=None):\n",
    "    \"\"\"Preprocess a given .csv\"\"\"\n",
    "    # read data\n",
    "    df = read_data(args.data_path, filter_data=filter_bs)\n",
    "    # handle nans\n",
    "    df = handle_nans(train_data=df, constant=args.nan_constant,\n",
    "                     identifier=args.identifier)\n",
    "    # split to train/validation\n",
    "    train_data, val_data = to_train_val(df)\n",
    "    \n",
    "    # handle outliers (if specified)\n",
    "    if args.outlier_detection is not None:\n",
    "        train_data = handle_outliers(df=train_data, columns=args.outlier_columns,\n",
    "                                     identifier=args.identifier, kwargs=args.outlier_kwargs)\n",
    "    \n",
    "    # get X and y\n",
    "    X_train, X_val, y_train, y_val = to_Xy(train_data=train_data, val_data=val_data,\n",
    "                                          targets=args.targets)\n",
    "    \n",
    "    # scale X\n",
    "    X_train, X_val, x_scaler = scale_features(train_data=X_train, val_data=X_val,\n",
    "                                             scaler=args.x_scaler, identifier=args.identifier)\n",
    "    # scale y\n",
    "    y_train, y_val, y_scaler = scale_features(train_data=y_train, val_data=y_val,\n",
    "                                             scaler=args.y_scaler, identifier=args.identifier)\n",
    "    \n",
    "    # generate time lags\n",
    "    X_train = generate_time_lags(X_train, args.num_lags)\n",
    "    X_val = generate_time_lags(X_val, args.num_lags)\n",
    "    y_train = generate_time_lags(y_train, args.num_lags, is_y=True)\n",
    "    y_val = generate_time_lags(y_val, args.num_lags, is_y=True)\n",
    "    \n",
    "    # get datetime features as exogenous data\n",
    "    date_time_df_train = time_to_feature(\n",
    "        X_train, args.use_time_features, identifier=args.identifier\n",
    "    )\n",
    "    date_time_df_val = time_to_feature(\n",
    "        X_val, args.use_time_features, identifier=args.identifier\n",
    "    )\n",
    "    \n",
    "    # get statistics as exogenous data\n",
    "    stats_df_train = assign_statistics(X_train, args.assign_stats, args.num_lags,\n",
    "                                       targets=args.targets, identifier=args.identifier)\n",
    "    stats_df_val = assign_statistics(X_val, args.assign_stats, args.num_lags, \n",
    "                                       targets=args.targets, identifier=args.identifier)\n",
    "    \n",
    "    # concat the exogenous features (if any) to a single dataframe\n",
    "    if date_time_df_train is not None or stats_df_train is not None:\n",
    "        exogenous_data_train = pd.concat([date_time_df_train, stats_df_train], axis=1)\n",
    "        # remove duplicate columns (if any)\n",
    "        exogenous_data_train = exogenous_data_train.loc[:, ~exogenous_data_train.columns.duplicated()].copy()\n",
    "        assert len(exogenous_data_train) == len(X_train) == len(y_train)\n",
    "    else:\n",
    "        exogenous_data_train = None\n",
    "    if date_time_df_val is not None or stats_df_val is not None:\n",
    "        exogenous_data_val = pd.concat([date_time_df_val, stats_df_val], axis=1)\n",
    "        exogenous_data_val = exogenous_data_val.loc[:, ~exogenous_data_val.columns.duplicated()].copy()\n",
    "        assert len(exogenous_data_val) == len(X_val) == len(y_val)\n",
    "    else:\n",
    "        exogenous_data_val = None\n",
    "        \n",
    "    return X_train, X_val, y_train, y_val, exogenous_data_train, exogenous_data_val, x_scaler, y_scaler"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "id": "66fc93eb",
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-08-17T12:16:16.734315Z",
     "end_time": "2023-08-17T12:16:16.826824Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO logger 2023-08-17 12:16:16,740 | data_utils.py:28 | Reading Stort1's data...\n",
      "INFO logger 2023-08-17 12:16:16,748 | data_utils.py:394 | \tTotal number of samples:  143\n",
      "INFO logger 2023-08-17 12:16:16,748 | data_utils.py:395 | \tNumber of samples for training: 115\n",
      "INFO logger 2023-08-17 12:16:16,749 | data_utils.py:396 | \tNumber of samples for validation:  28\n"
     ]
    }
   ],
   "source": [
    "# here exogenous_data_train and val are None.\n",
    "X_train, X_val, y_train, y_val, exogenous_data_train, exogenous_data_val, x_scaler, y_scaler = make_preprocessing(\n",
    "        filter_bs=\"Stort1\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "id": "9b99c6f2",
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-08-17T12:16:16.783313Z",
     "end_time": "2023-08-17T12:16:16.843828Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": "            Unemployment_lag-1  CPI_lag-1  Fuel_Price_lag-1  \\\nDate                                                          \n2010-02-12            1.635193  -0.992657         -1.317322   \n2010-02-19            1.635193  -0.949996         -1.373046   \n2010-02-26            1.635193  -0.936255         -1.451988   \n2010-03-05            1.635193  -0.927331         -1.342862   \n2010-03-12            1.635193  -0.918406         -1.194266   \n\n            Temperature_lag-1  Holiday_Flag_lag-1  Weekly_Sales_lag-1 District  \nDate                                                                            \n2010-02-12          -1.615538           -0.291386            0.545891   Stort1  \n2010-02-19          -1.871053            3.431877            0.535605   Stort1  \n2010-02-26          -1.775571           -0.291386            0.357647   Stort1  \n2010-03-05          -1.325058           -0.291386           -0.842454   Stort1  \n2010-03-12          -1.333800           -0.291386            0.018449   Stort1  ",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>Unemployment_lag-1</th>\n      <th>CPI_lag-1</th>\n      <th>Fuel_Price_lag-1</th>\n      <th>Temperature_lag-1</th>\n      <th>Holiday_Flag_lag-1</th>\n      <th>Weekly_Sales_lag-1</th>\n      <th>District</th>\n    </tr>\n    <tr>\n      <th>Date</th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n      <th></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>2010-02-12</th>\n      <td>1.635193</td>\n      <td>-0.992657</td>\n      <td>-1.317322</td>\n      <td>-1.615538</td>\n      <td>-0.291386</td>\n      <td>0.545891</td>\n      <td>Stort1</td>\n    </tr>\n    <tr>\n      <th>2010-02-19</th>\n      <td>1.635193</td>\n      <td>-0.949996</td>\n      <td>-1.373046</td>\n      <td>-1.871053</td>\n      <td>3.431877</td>\n      <td>0.535605</td>\n      <td>Stort1</td>\n    </tr>\n    <tr>\n      <th>2010-02-26</th>\n      <td>1.635193</td>\n      <td>-0.936255</td>\n      <td>-1.451988</td>\n      <td>-1.775571</td>\n      <td>-0.291386</td>\n      <td>0.357647</td>\n      <td>Stort1</td>\n    </tr>\n    <tr>\n      <th>2010-03-05</th>\n      <td>1.635193</td>\n      <td>-0.927331</td>\n      <td>-1.342862</td>\n      <td>-1.325058</td>\n      <td>-0.291386</td>\n      <td>-0.842454</td>\n      <td>Stort1</td>\n    </tr>\n    <tr>\n      <th>2010-03-12</th>\n      <td>1.635193</td>\n      <td>-0.918406</td>\n      <td>-1.194266</td>\n      <td>-1.333800</td>\n      <td>-0.291386</td>\n      <td>0.018449</td>\n      <td>Stort1</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X_train.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "id": "ec22537f",
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-08-17T12:16:16.798315Z",
     "end_time": "2023-08-17T12:16:16.843828Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": "            Weekly_Sales District\nDate                             \n2010-02-12      0.535605   Stort1\n2010-02-19      0.357647   Stort1\n2010-02-26     -0.842454   Stort1\n2010-03-05      0.018449   Stort1\n2010-03-12     -0.665537   Stort1",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>Weekly_Sales</th>\n      <th>District</th>\n    </tr>\n    <tr>\n      <th>Date</th>\n      <th></th>\n      <th></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>2010-02-12</th>\n      <td>0.535605</td>\n      <td>Stort1</td>\n    </tr>\n    <tr>\n      <th>2010-02-19</th>\n      <td>0.357647</td>\n      <td>Stort1</td>\n    </tr>\n    <tr>\n      <th>2010-02-26</th>\n      <td>-0.842454</td>\n      <td>Stort1</td>\n    </tr>\n    <tr>\n      <th>2010-03-05</th>\n      <td>0.018449</td>\n      <td>Stort1</td>\n    </tr>\n    <tr>\n      <th>2010-03-12</th>\n      <td>-0.665537</td>\n      <td>Stort1</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y_train.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "id": "367c2b33",
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-08-17T12:16:16.814318Z",
     "end_time": "2023-08-17T12:16:16.844826Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": "(StandardScaler(), StandardScaler())"
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x_scaler, y_scaler"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "488a9c30",
   "metadata": {},
   "source": [
    "### Postprocessing Stage\n",
    "\n",
    "In this stage we transform data in a way that can be fed into ML algorithms."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "id": "c417082c",
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-08-17T12:16:16.836828Z",
     "end_time": "2023-08-17T12:16:16.844826Z"
    }
   },
   "outputs": [],
   "source": [
    "def make_postprocessing(X_train, X_val, y_train, y_val, exogenous_data_train, exogenous_data_val, x_scaler, y_scaler):\n",
    "    \"\"\"Make data ready to be fed into ml algorithms\"\"\"\n",
    "    # if there are more than one specified areas, get the data per area\n",
    "    if X_train[args.identifier].nunique() != 1:\n",
    "        area_X_train, area_X_val, area_y_train, area_y_val = get_data_by_area(X_train, X_val,\n",
    "                                                                              y_train, y_val, \n",
    "                                                                              identifier=args.identifier)\n",
    "    else:\n",
    "        area_X_train, area_X_val, area_y_train, area_y_val = None, None, None, None\n",
    "\n",
    "    # Get the exogenous data per area.\n",
    "    if exogenous_data_train is not None:\n",
    "        exogenous_data_train, exogenous_data_val = get_exogenous_data_by_area(exogenous_data_train,\n",
    "                                                                              exogenous_data_val)\n",
    "    # transform to np\n",
    "    if area_X_train is not None:\n",
    "        for area in area_X_train:\n",
    "            tmp_X_train, tmp_y_train, tmp_X_val, tmp_y_val = remove_identifiers(\n",
    "                area_X_train[area], area_y_train[area], area_X_val[area], area_y_val[area])\n",
    "            tmp_X_train, tmp_y_train = tmp_X_train.to_numpy(), tmp_y_train.to_numpy()\n",
    "            tmp_X_val, tmp_y_val = tmp_X_val.to_numpy(), tmp_y_val.to_numpy()\n",
    "            area_X_train[area] = tmp_X_train\n",
    "            area_X_val[area] = tmp_X_val\n",
    "            area_y_train[area] = tmp_y_train\n",
    "            area_y_val[area] = tmp_y_val\n",
    "    \n",
    "    if exogenous_data_train is not None:\n",
    "        for area in exogenous_data_train:\n",
    "            exogenous_data_train[area] = exogenous_data_train[area].to_numpy()\n",
    "            exogenous_data_val[area] = exogenous_data_val[area].to_numpy()\n",
    "    \n",
    "    # remove identifiers from features, targets\n",
    "    X_train, y_train, X_val, y_val = remove_identifiers(X_train, y_train, X_val, y_val)\n",
    "    assert len(X_train.columns) == len(X_val.columns)\n",
    "    \n",
    "    num_features = len(X_train.columns) // args.num_lags\n",
    "    \n",
    "    # to timeseries representation\n",
    "    X_train = to_timeseries_rep(X_train.to_numpy(), num_lags=args.num_lags,\n",
    "                                            num_features=num_features)\n",
    "    X_val = to_timeseries_rep(X_val.to_numpy(), num_lags=args.num_lags,\n",
    "                                          num_features=num_features)\n",
    "    \n",
    "    if area_X_train is not None:\n",
    "        area_X_train = to_timeseries_rep(area_X_train, num_lags=args.num_lags,\n",
    "                                                     num_features=num_features)\n",
    "        area_X_val = to_timeseries_rep(area_X_val, num_lags=args.num_lags,\n",
    "                                                   num_features=num_features)\n",
    "    \n",
    "    # transform targets to numpy\n",
    "    y_train, y_val = y_train.to_numpy(), y_val.to_numpy()\n",
    "    \n",
    "    # centralized (all) learning specific\n",
    "    if not args.filter_bs and exogenous_data_train is not None:\n",
    "        exogenous_data_train_combined, exogenous_data_val_combined = [], []\n",
    "        for area in exogenous_data_train:\n",
    "            exogenous_data_train_combined.extend(exogenous_data_train[area])\n",
    "            exogenous_data_val_combined.extend(exogenous_data_val[area])\n",
    "        exogenous_data_train_combined = np.stack(exogenous_data_train_combined)\n",
    "        exogenous_data_val_combined = np.stack(exogenous_data_val_combined)\n",
    "        exogenous_data_train[\"all\"] = exogenous_data_train_combined\n",
    "        exogenous_data_val[\"all\"] = exogenous_data_val_combined\n",
    "    return X_train, X_val, y_train, y_val, area_X_train, area_X_val, area_y_train, area_y_val, exogenous_data_train, exogenous_data_val"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "id": "00c59dca",
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-08-17T12:16:16.846826Z",
     "end_time": "2023-08-17T12:16:16.895826Z"
    }
   },
   "outputs": [],
   "source": [
    "X_train, X_val, y_train, y_val, area_X_train, area_X_val, area_y_train, area_y_val, exogenous_data_train, exogenous_data_val = make_postprocessing(X_train, X_val, y_train, y_val, exogenous_data_train, exogenous_data_val, x_scaler, y_scaler)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "id": "9171667b",
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-08-17T12:16:16.862826Z",
     "end_time": "2023-08-17T12:16:16.969931Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": "array([[[[ 1.63519263],\n         [-0.99265677],\n         [-1.31732237],\n         [-1.61553836],\n         [-0.29138577],\n         [ 0.54589117]]],\n\n\n       [[[ 1.63519263],\n         [-0.94999582],\n         [-1.37304604],\n         [-1.87105346],\n         [ 3.43187666],\n         [ 0.53560525]]]])"
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X_train[:2]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "id": "2949d425",
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-08-17T12:16:16.877826Z",
     "end_time": "2023-08-17T12:16:16.980932Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": "array([[0.53560525],\n       [0.35764733]], dtype=float32)"
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y_train[:2]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "id": "bf7bb251",
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-08-17T12:16:16.894825Z",
     "end_time": "2023-08-17T12:16:16.992933Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": "(114, 27)"
     },
     "execution_count": 48,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(X_train), len(X_val)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "67a83357",
   "metadata": {},
   "source": [
    "### Define the input dimensions for the model architecture"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "id": "e1486173",
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-08-17T12:16:16.911828Z",
     "end_time": "2023-08-17T12:16:17.065440Z"
    }
   },
   "outputs": [],
   "source": [
    "def get_input_dims(X_train, exogenous_data_train):\n",
    "    if args.model_name == \"mlp\":\n",
    "        input_dim = X_train.shape[1] * X_train.shape[2]\n",
    "    else:\n",
    "        input_dim = X_train.shape[2]\n",
    "    \n",
    "    if exogenous_data_train is not None:\n",
    "        if len(exogenous_data_train) == 1:\n",
    "            cid = next(iter(exogenous_data_train.keys()))\n",
    "            exogenous_dim = exogenous_data_train[cid].shape[1]\n",
    "        else:\n",
    "            exogenous_dim = exogenous_data_train[\"all\"].shape[1]\n",
    "    else:\n",
    "        exogenous_dim = 0\n",
    "    \n",
    "    return input_dim, exogenous_dim"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "be6783ff",
   "metadata": {},
   "source": [
    "### Initialize the model for training"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "id": "5e7044d5",
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-08-17T12:16:16.928932Z",
     "end_time": "2023-08-17T12:16:17.089440Z"
    }
   },
   "outputs": [],
   "source": [
    "def get_model(model: str,\n",
    "              input_dim: int,\n",
    "              out_dim: int,\n",
    "              lags: int = 5,\n",
    "              exogenous_dim: int = 0,\n",
    "              seed=0):\n",
    "    if model == \"mlp\":\n",
    "        model = MLP(input_dim=input_dim, layer_units=[256, 128, 64], num_outputs=out_dim)\n",
    "    elif model == \"rnn\":\n",
    "        model = RNN(input_dim=input_dim, rnn_hidden_size=128, num_rnn_layers=1, rnn_dropout=0.0,\n",
    "                    layer_units=[128], num_outputs=out_dim, matrix_rep=True, exogenous_dim=exogenous_dim)\n",
    "    elif model == \"lstm\":\n",
    "        model = LSTM(input_dim=input_dim, lstm_hidden_size=128, num_lstm_layers=1, lstm_dropout=0.0,\n",
    "                     layer_units=[128], num_outputs=out_dim, matrix_rep=True, exogenous_dim=exogenous_dim)\n",
    "    elif model == \"gru\":\n",
    "        model = GRU(input_dim=input_dim, gru_hidden_size=128, num_gru_layers=1, gru_dropout=0.0,\n",
    "                    layer_units=[128], num_outputs=out_dim, matrix_rep=True, exogenous_dim=exogenous_dim)\n",
    "    elif model == \"cnn\":\n",
    "        model = CNN(num_features=input_dim, lags=lags, exogenous_dim=exogenous_dim, out_dim=out_dim)\n",
    "    elif model == \"da_encoder_decoder\":\n",
    "        model = DualAttentionAutoEncoder(input_dim=input_dim, architecture=\"lstm\", matrix_rep=True)\n",
    "    else:\n",
    "        raise NotImplementedError(\"Specified model is not implemented. Plese define your own model or choose one from ['mlp', 'rnn', 'lstm', 'gru', 'cnn', 'da_encoder_decoder']\")\n",
    "    return model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "id": "44ed1dae",
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-08-17T12:16:16.941932Z",
     "end_time": "2023-08-17T12:16:17.106441Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "6 0\n"
     ]
    }
   ],
   "source": [
    "# define the model\n",
    "args.model_name = \"lstm\"\n",
    "\n",
    "input_dim, exogenous_dim = get_input_dims(X_train, exogenous_data_train)\n",
    "\n",
    "print(input_dim, exogenous_dim)\n",
    "\n",
    "model = get_model(model=args.model_name,\n",
    "                  input_dim=input_dim,\n",
    "                  out_dim=y_train.shape[1],\n",
    "                  lags=args.num_lags,\n",
    "                  exogenous_dim=exogenous_dim,\n",
    "                  seed=args.seed)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "id": "8f285c4b",
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-08-17T12:16:16.958932Z",
     "end_time": "2023-08-17T12:16:17.107441Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": "LSTM(\n  (lstm): LSTM(6, 128, batch_first=True)\n  (MLP_layers): Sequential(\n    (0): Linear(in_features=128, out_features=1, bias=True)\n  )\n)"
     },
     "execution_count": 52,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f2473d72",
   "metadata": {},
   "source": [
    "### The fit function used to train the model specified above"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "id": "6b11fc63",
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-08-17T12:16:16.971931Z",
     "end_time": "2023-08-17T12:16:17.107441Z"
    }
   },
   "outputs": [],
   "source": [
    "def fit(model, X_train, y_train, X_val, y_val, \n",
    "        exogenous_data_train=None, exogenous_data_val=None, \n",
    "        idxs=[1], # the indices of our targets in X\n",
    "        log_per=1):\n",
    "    \n",
    "    # get exogenous data (if any)\n",
    "    if exogenous_data_train is not None and len(exogenous_data_train) > 1:\n",
    "        exogenous_data_train = exogenous_data_train[\"all\"]\n",
    "        exogenous_data_val = exogenous_data_val[\"all\"]\n",
    "    elif exogenous_data_train is not None and len(exogenous_data_train) == 1:\n",
    "        cid = next(iter(exogenous_data_train.keys()))\n",
    "        exogenous_data_train = exogenous_data_train[cid]\n",
    "        exogenous_data_val = exogenous_data_val[cid]\n",
    "    else:\n",
    "        exogenous_data_train = None\n",
    "        exogenous_data_val = None\n",
    "    num_features = len(X_train[0][0])\n",
    "    \n",
    "    # to torch loader\n",
    "    train_loader = to_torch_dataset(X_train, y_train,\n",
    "                                    num_lags=args.num_lags,\n",
    "                                    num_features=num_features,\n",
    "                                    exogenous_data=exogenous_data_train,\n",
    "                                    indices=idxs,\n",
    "                                    batch_size=args.batch_size, \n",
    "                                    shuffle=False)\n",
    "    val_loader = to_torch_dataset(X_val, y_val, \n",
    "                                  num_lags=args.num_lags,\n",
    "                                  num_features=num_features,\n",
    "                                  exogenous_data=exogenous_data_val,\n",
    "                                  indices=idxs,\n",
    "                                  batch_size=args.batch_size,\n",
    "                                  shuffle=False)\n",
    "    \n",
    "    # train the model\n",
    "    model = train(model, \n",
    "                  train_loader, val_loader,\n",
    "                  epochs=args.epochs,\n",
    "                  optimizer=args.optimizer, lr=args.lr,\n",
    "                  criterion=args.criterion,\n",
    "                  early_stopping=args.early_stopping,\n",
    "                  patience=args.patience,\n",
    "                  plot_history=args.plot_history, \n",
    "                  device=device, log_per=log_per)\n",
    "    \n",
    "    return model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "id": "681cc512",
   "metadata": {
    "scrolled": false,
    "ExecuteTime": {
     "start_time": "2023-08-17T12:16:16.991933Z",
     "end_time": "2023-08-17T12:16:18.085031Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO logger 2023-08-17 12:16:17,012 | train_utils.py:97 | Epoch 1 [Train]: loss 1.0028414726257324, mse: 0.9913489818572998, rmse: 0.995665095228963, mae 0.6778193712234497, r2: 0.014695752120353456, nrmse: -207.92847988860308\n",
      "INFO logger 2023-08-17 12:16:17,013 | train_utils.py:99 | Epoch 1 [Test]: loss 0.009520664259239479, mse: 0.25705793499946594, rmse: 0.5070088115599826, mae 0.41209590435028076, r2: -0.1005160721328977, nrmse: 4.270668771716597\n",
      "INFO logger 2023-08-17 12:16:17,013 | helpers.py:147 | Validation loss decreased (inf --> 0.009521). Caching model ...\n",
      "INFO logger 2023-08-17 12:16:17,032 | train_utils.py:97 | Epoch 2 [Train]: loss 0.9913491010665894, mse: 0.9804699420928955, rmse: 0.9901868218133867, mae 0.6700534224510193, r2: 0.02550852666205161, nrmse: -206.78443148400075\n",
      "INFO logger 2023-08-17 12:16:17,033 | train_utils.py:99 | Epoch 2 [Test]: loss 0.009393607024793272, mse: 0.25362738966941833, rmse: 0.5036143263147091, mae 0.4115025997161865, r2: -0.08582915171428818, nrmse: 4.2420761283492405\n",
      "INFO logger 2023-08-17 12:16:17,033 | helpers.py:147 | Validation loss decreased (0.009521 --> 0.009394). Caching model ...\n",
      "INFO logger 2023-08-17 12:16:17,048 | train_utils.py:97 | Epoch 3 [Train]: loss 0.9804699420928955, mse: 0.9701988697052002, rmse: 0.9849867358016554, mae 0.6629652976989746, r2: 0.03571695820133802, nrmse: -205.69847799934973\n",
      "INFO logger 2023-08-17 12:16:17,048 | train_utils.py:99 | Epoch 3 [Test]: loss 0.009300549825032553, mse: 0.2511148452758789, rmse: 0.5011136051594278, mae 0.4115152657032013, r2: -0.0750724802392293, nrmse: 4.221011895339618\n",
      "INFO logger 2023-08-17 12:16:17,049 | helpers.py:147 | Validation loss decreased (0.009394 --> 0.009301). Caching model ...\n",
      "INFO logger 2023-08-17 12:16:17,067 | train_utils.py:97 | Epoch 4 [Train]: loss 0.970198929309845, mse: 0.9605147838592529, rmse: 0.9800585614437808, mae 0.6570010185241699, r2: 0.04534199936538852, nrmse: -204.66930884621877\n",
      "INFO logger 2023-08-17 12:16:17,068 | train_utils.py:99 | Epoch 4 [Test]: loss 0.009241855254879704, mse: 0.24953009188175201, rmse: 0.49952987086034406, mae 0.4123363494873047, r2: -0.06828781261461603, nrmse: 4.207671684164623\n",
      "INFO logger 2023-08-17 12:16:17,069 | helpers.py:147 | Validation loss decreased (0.009301 --> 0.009242). Caching model ...\n",
      "INFO logger 2023-08-17 12:16:17,083 | train_utils.py:97 | Epoch 5 [Train]: loss 0.9605147838592529, mse: 0.9513853788375854, rmse: 0.9753898599214498, mae 0.6517890095710754, r2: 0.05441577399893349, nrmse: -203.69432637948012\n",
      "INFO logger 2023-08-17 12:16:17,084 | train_utils.py:99 | Epoch 5 [Test]: loss 0.009219224806185122, mse: 0.2489190697669983, rmse: 0.4989178988240433, mae 0.41394826769828796, r2: -0.06567184911721924, nrmse: 4.202516882502396\n",
      "INFO logger 2023-08-17 12:16:17,084 | helpers.py:147 | Validation loss decreased (0.009242 --> 0.009219). Caching model ...\n",
      "INFO logger 2023-08-17 12:16:17,101 | train_utils.py:97 | Epoch 6 [Train]: loss 0.9513853192329407, mse: 0.9427734613418579, rmse: 0.9709652214893476, mae 0.6469023823738098, r2: 0.06297519526745887, nrmse: -202.7703125241665\n",
      "INFO logger 2023-08-17 12:16:17,102 | train_utils.py:99 | Epoch 6 [Test]: loss 0.00923581255806817, mse: 0.24936693906784058, rmse: 0.49936653779347345, mae 0.41746100783348083, r2: -0.06758929639454814, nrmse: 4.206295886718566\n",
      "INFO logger 2023-08-17 12:16:17,102 | helpers.py:135 | EarlyStopping counter: 1 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,124 | train_utils.py:97 | Epoch 7 [Train]: loss 0.9427734017372131, mse: 0.934643030166626, rmse: 0.9667693779628241, mae 0.6424477696418762, r2: 0.07105598730661322, nrmse: -201.89407876795573\n",
      "INFO logger 2023-08-17 12:16:17,125 | train_utils.py:99 | Epoch 7 [Test]: loss 0.009295590497829296, mse: 0.250980943441391, rmse: 0.5009799830745646, mae 0.42096495628356934, r2: -0.07449919028020568, nrmse: 4.219886361321223\n",
      "INFO logger 2023-08-17 12:16:17,125 | helpers.py:135 | EarlyStopping counter: 2 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,139 | train_utils.py:97 | Epoch 8 [Train]: loss 0.9346430897712708, mse: 0.9269633293151855, rmse: 0.9627893483598505, mae 0.6388933658599854, r2: 0.0786888864202333, nrmse: -201.0629142436358\n",
      "INFO logger 2023-08-17 12:16:17,140 | train_utils.py:99 | Epoch 8 [Test]: loss 0.009402531164663809, mse: 0.25386837124824524, rmse: 0.5038535216193742, mae 0.42444705963134766, r2: -0.08686078485034043, nrmse: 4.244090933407226\n",
      "INFO logger 2023-08-17 12:16:17,140 | helpers.py:135 | EarlyStopping counter: 3 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,170 | train_utils.py:97 | Epoch 9 [Train]: loss 0.9269633293151855, mse: 0.9197098016738892, rmse: 0.959015016396453, mae 0.6355710029602051, r2: 0.08589816640278825, nrmse: -200.27470632964466\n",
      "INFO logger 2023-08-17 12:16:17,171 | train_utils.py:99 | Epoch 9 [Test]: loss 0.009559941512567026, mse: 0.2581183910369873, rmse: 0.5080535316647128, mae 0.4278913736343384, r2: -0.10505607976062725, nrmse: 4.2794687243500205\n",
      "INFO logger 2023-08-17 12:16:17,171 | helpers.py:135 | EarlyStopping counter: 4 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,186 | train_utils.py:97 | Epoch 10 [Train]: loss 0.9197098612785339, mse: 0.912864089012146, rmse: 0.9554392126201153, mae 0.6324872374534607, r2: 0.0927021273402463, nrmse: -199.52795780229687\n",
      "INFO logger 2023-08-17 12:16:17,187 | train_utils.py:99 | Epoch 10 [Test]: loss 0.009769928676110727, mse: 0.2637880742549896, rmse: 0.5136030317813454, mae 0.43127956986427307, r2: -0.12932900171327244, nrmse: 4.326213625634515\n",
      "INFO logger 2023-08-17 12:16:17,188 | helpers.py:135 | EarlyStopping counter: 5 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,231 | train_utils.py:97 | Epoch 11 [Train]: loss 0.9128641486167908, mse: 0.9064117670059204, rmse: 0.9520565986357746, mae 0.6296549439430237, r2: 0.09911520338324042, nrmse: -198.82155382450938\n",
      "INFO logger 2023-08-17 12:16:17,232 | train_utils.py:99 | Epoch 11 [Test]: loss 0.010033036823625918, mse: 0.2708919942378998, rmse: 0.5204728563891683, mae 0.43592360615730286, r2: -0.15974230282120838, nrmse: 4.384079967896948\n",
      "INFO logger 2023-08-17 12:16:17,232 | helpers.py:135 | EarlyStopping counter: 6 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,248 | train_utils.py:97 | Epoch 12 [Train]: loss 0.9064117670059204, mse: 0.9003402590751648, rmse: 0.9488626133825512, mae 0.6271281242370605, r2: 0.1051496829819848, nrmse: -198.15454189281496\n",
      "INFO logger 2023-08-17 12:16:17,248 | train_utils.py:99 | Epoch 12 [Test]: loss 0.0103479888704088, mse: 0.2793956995010376, rmse: 0.5285789434900312, mae 0.44106122851371765, r2: -0.1961484419800672, nrmse: 4.452359674784004\n",
      "INFO logger 2023-08-17 12:16:17,249 | helpers.py:135 | EarlyStopping counter: 7 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,262 | train_utils.py:97 | Epoch 13 [Train]: loss 0.9003400802612305, mse: 0.8946374654769897, rmse: 0.945852771564893, mae 0.624934732913971, r2: 0.11081756949772337, nrmse: -197.52598532610426\n",
      "INFO logger 2023-08-17 12:16:17,263 | train_utils.py:99 | Epoch 13 [Test]: loss 0.010711556231534039, mse: 0.28921201825141907, rmse: 0.5377843603633514, mae 0.4462601840496063, r2: -0.23817399258929361, nrmse: 4.529899325920561\n",
      "INFO logger 2023-08-17 12:16:17,263 | helpers.py:135 | EarlyStopping counter: 8 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,286 | train_utils.py:97 | Epoch 14 [Train]: loss 0.8946375250816345, mse: 0.889290988445282, rmse: 0.9430222629637552, mae 0.6232947111129761, r2: 0.11613157172203636, nrmse: -196.93487958827495\n",
      "INFO logger 2023-08-17 12:16:17,287 | train_utils.py:99 | Epoch 14 [Test]: loss 0.011118451754252115, mse: 0.30019819736480713, rmse: 0.5479034562446263, mae 0.4540027976036072, r2: -0.28520806802750465, nrmse: 4.615135136014671\n",
      "INFO logger 2023-08-17 12:16:17,288 | helpers.py:135 | EarlyStopping counter: 9 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,304 | train_utils.py:97 | Epoch 15 [Train]: loss 0.8892909288406372, mse: 0.8842860460281372, rmse: 0.9403648472949939, mae 0.6217104196548462, r2: 0.12110600068581201, nrmse: -196.37992149736124\n",
      "INFO logger 2023-08-17 12:16:17,305 | train_utils.py:99 | Epoch 15 [Test]: loss 0.011561275632293136, mse: 0.3121544420719147, rmse: 0.5587078324776865, mae 0.4626302123069763, r2: -0.3363951542233703, nrmse: 4.706143243022587\n",
      "INFO logger 2023-08-17 12:16:17,305 | helpers.py:135 | EarlyStopping counter: 10 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,327 | train_utils.py:97 | Epoch 16 [Train]: loss 0.8842859864234924, mse: 0.8796061873435974, rmse: 0.9378732256246562, mae 0.6202331781387329, r2: 0.1257573022236197, nrmse: -195.85958678958315\n",
      "INFO logger 2023-08-17 12:16:17,328 | train_utils.py:99 | Epoch 16 [Test]: loss 0.012030531962712606, mse: 0.32482433319091797, rmse: 0.5699336217410919, mae 0.4736633598804474, r2: -0.39063744025757186, nrmse: 4.800701022990134\n",
      "INFO logger 2023-08-17 12:16:17,328 | helpers.py:135 | EarlyStopping counter: 11 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,348 | train_utils.py:97 | Epoch 17 [Train]: loss 0.8796061277389526, mse: 0.8752321600914001, rmse: 0.9355384332518896, mae 0.6189966201782227, r2: 0.13010449796525136, nrmse: -195.37200333280518\n",
      "INFO logger 2023-08-17 12:16:17,349 | train_utils.py:99 | Epoch 17 [Test]: loss 0.012514789899190268, mse: 0.3378993570804596, rmse: 0.5812911121636556, mae 0.4845636785030365, r2: -0.44661415378778835, nrmse: 4.896368156512872\n",
      "INFO logger 2023-08-17 12:16:17,349 | helpers.py:135 | EarlyStopping counter: 12 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,361 | train_utils.py:97 | Epoch 18 [Train]: loss 0.8752322793006897, mse: 0.871142566204071, rmse: 0.9333501841238748, mae 0.6181235313415527, r2: 0.134169275585439, nrmse: -194.91502305199998\n",
      "INFO logger 2023-08-17 12:16:17,362 | train_utils.py:99 | Epoch 18 [Test]: loss 0.01300110309212296, mse: 0.35102978348731995, rmse: 0.5924776649691699, mae 0.4947042167186737, r2: -0.5028281962373271, nrmse: 4.990595437460269\n",
      "INFO logger 2023-08-17 12:16:17,362 | helpers.py:135 | EarlyStopping counter: 13 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,388 | train_utils.py:97 | Epoch 19 [Train]: loss 0.8711426258087158, mse: 0.8673123717308044, rmse: 0.9312960709306168, mae 0.6174941658973694, r2: 0.13797609870001348, nrmse: -194.48605488204015\n",
      "INFO logger 2023-08-17 12:16:17,389 | train_utils.py:99 | Epoch 19 [Test]: loss 0.013475603527492948, mse: 0.36384129524230957, rmse: 0.6031925855332686, mae 0.5039700269699097, r2: -0.5576767948568613, nrmse: 5.080850035804872\n",
      "INFO logger 2023-08-17 12:16:17,389 | helpers.py:135 | EarlyStopping counter: 14 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,405 | train_utils.py:97 | Epoch 20 [Train]: loss 0.8673123717308044, mse: 0.863715410232544, rmse: 0.9293629055608708, mae 0.6168296337127686, r2: 0.14155115271740593, nrmse: -194.08234470014193\n",
      "INFO logger 2023-08-17 12:16:17,405 | train_utils.py:99 | Epoch 20 [Test]: loss 0.013924273075880829, mse: 0.37595537304878235, rmse: 0.6131519983240553, mae 0.5122584700584412, r2: -0.6095394296599492, nrmse: 5.164740793165438\n",
      "INFO logger 2023-08-17 12:16:17,406 | helpers.py:135 | EarlyStopping counter: 15 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,460 | train_utils.py:97 | Epoch 21 [Train]: loss 0.8637153506278992, mse: 0.8603241443634033, rmse: 0.927536600012853, mae 0.6164190769195557, r2: 0.14492170658846715, nrmse: -193.70095045600192\n",
      "INFO logger 2023-08-17 12:16:17,461 | train_utils.py:99 | Epoch 21 [Test]: loss 0.014333782372651276, mse: 0.3870121240615845, rmse: 0.6221029850929704, mae 0.51948481798172, r2: -0.6568756062491596, nrmse: 5.240137312512777\n",
      "INFO logger 2023-08-17 12:16:17,462 | helpers.py:135 | EarlyStopping counter: 16 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,482 | train_utils.py:97 | Epoch 22 [Train]: loss 0.8603242039680481, mse: 0.8571122288703918, rmse: 0.9258035584671253, mae 0.6162091493606567, r2: 0.14811408297533724, nrmse: -193.33903288360364\n",
      "INFO logger 2023-08-17 12:16:17,482 | train_utils.py:99 | Epoch 22 [Test]: loss 0.014692312037503277, mse: 0.3966924250125885, rmse: 0.6298352364012262, mae 0.5255857706069946, r2: -0.6983190606359408, nrmse: 5.30526810204606\n",
      "INFO logger 2023-08-17 12:16:17,483 | helpers.py:135 | EarlyStopping counter: 17 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,494 | train_utils.py:97 | Epoch 23 [Train]: loss 0.8571122288703918, mse: 0.8540546298027039, rmse: 0.9241507614035189, mae 0.6159362196922302, r2: 0.15115304368063642, nrmse: -192.99387306767076\n",
      "INFO logger 2023-08-17 12:16:17,494 | train_utils.py:99 | Epoch 23 [Test]: loss 0.014990277864314892, mse: 0.40473753213882446, rmse: 0.6361898554196102, mae 0.5305224657058716, r2: -0.7327615729520329, nrmse: 5.358794731917577\n",
      "INFO logger 2023-08-17 12:16:17,495 | helpers.py:135 | EarlyStopping counter: 18 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,506 | train_utils.py:97 | Epoch 24 [Train]: loss 0.8540545701980591, mse: 0.8511297106742859, rmse: 0.9225669139278114, mae 0.6156012415885925, r2: 0.1540601171877768, nrmse: -192.6631122530381\n",
      "INFO logger 2023-08-17 12:16:17,506 | train_utils.py:99 | Epoch 24 [Test]: loss 0.015220823111357513, mse: 0.4109622538089752, rmse: 0.6410633773730763, mae 0.5342811942100525, r2: -0.7594108315295549, nrmse: 5.399845691073305\n",
      "INFO logger 2023-08-17 12:16:17,507 | helpers.py:135 | EarlyStopping counter: 19 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,521 | train_utils.py:97 | Epoch 25 [Train]: loss 0.8511296510696411, mse: 0.8483194708824158, rmse: 0.9210425999281552, mae 0.6152085661888123, r2: 0.15685321881494763, nrmse: -192.3447840377173\n",
      "INFO logger 2023-08-17 12:16:17,521 | train_utils.py:99 | Epoch 25 [Test]: loss 0.015380086722197357, mse: 0.41526228189468384, rmse: 0.6444084744125296, mae 0.5368728041648865, r2: -0.7778203431833406, nrmse: 5.428022324573618\n",
      "INFO logger 2023-08-17 12:16:17,522 | helpers.py:135 | EarlyStopping counter: 20 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,534 | train_utils.py:97 | Epoch 26 [Train]: loss 0.8483194708824158, mse: 0.8456097841262817, rmse: 0.919570434565119, mae 0.6147650480270386, r2: 0.15954634480541907, nrmse: -192.03734621796488\n",
      "INFO logger 2023-08-17 12:16:17,535 | train_utils.py:99 | Epoch 26 [Test]: loss 0.015467179042321665, mse: 0.41761377453804016, rmse: 0.6462304345495036, mae 0.5387665629386902, r2: -0.7878876244204445, nrmse: 5.443369174732585\n",
      "INFO logger 2023-08-17 12:16:17,535 | helpers.py:135 | EarlyStopping counter: 21 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,549 | train_utils.py:97 | Epoch 27 [Train]: loss 0.8456097841262817, mse: 0.8429902791976929, rmse: 0.9181450207879434, mae 0.6142800450325012, r2: 0.16214988417548581, nrmse: -191.73967170740846\n",
      "INFO logger 2023-08-17 12:16:17,550 | train_utils.py:99 | Epoch 27 [Test]: loss 0.015483977618040863, mse: 0.4180673658847809, rmse: 0.6465812910104815, mae 0.539459764957428, r2: -0.7898294550222409, nrmse: 5.446324531123025\n",
      "INFO logger 2023-08-17 12:16:17,550 | helpers.py:135 | EarlyStopping counter: 22 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,564 | train_utils.py:97 | Epoch 28 [Train]: loss 0.8429902791976929, mse: 0.8404534459114075, rmse: 0.9167624806412005, mae 0.6137648224830627, r2: 0.16467125767079194, nrmse: -191.4509506580569\n",
      "INFO logger 2023-08-17 12:16:17,565 | train_utils.py:99 | Epoch 28 [Test]: loss 0.015434704445026539, mse: 0.41673702001571655, rmse: 0.6455517175375778, mae 0.5390030741691589, r2: -0.7841339564146725, nrmse: 5.437652162559274\n",
      "INFO logger 2023-08-17 12:16:17,565 | helpers.py:135 | EarlyStopping counter: 23 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,577 | train_utils.py:97 | Epoch 29 [Train]: loss 0.8404534459114075, mse: 0.8379941582679749, rmse: 0.9154202085752613, mae 0.6132317185401917, r2: 0.16711550450129886, nrmse: -191.17063894319912\n",
      "INFO logger 2023-08-17 12:16:17,577 | train_utils.py:99 | Epoch 29 [Test]: loss 0.015325452442522402, mse: 0.41378724575042725, rmse: 0.643262967805879, mae 0.5374886393547058, r2: -0.7715050742373686, nrmse: 5.418373420686197\n",
      "INFO logger 2023-08-17 12:16:17,578 | helpers.py:135 | EarlyStopping counter: 24 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,589 | train_utils.py:97 | Epoch 30 [Train]: loss 0.8379942178726196, mse: 0.835608959197998, rmse: 0.9141164910436733, mae 0.612693727016449, r2: 0.16948616594604904, nrmse: -190.8983787164962\n",
      "INFO logger 2023-08-17 12:16:17,590 | train_utils.py:99 | Epoch 30 [Test]: loss 0.015163609275111446, mse: 0.40941742062568665, rmse: 0.6398573439647987, mae 0.5350182056427002, r2: -0.7527972888050627, nrmse: 5.3896869539923244\n",
      "INFO logger 2023-08-17 12:16:17,591 | helpers.py:135 | EarlyStopping counter: 25 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,608 | train_utils.py:97 | Epoch 31 [Train]: loss 0.8356090188026428, mse: 0.8332954049110413, rmse: 0.9128501546864312, mae 0.6121635437011719, r2: 0.1717856002009519, nrmse: -190.63392494077308\n",
      "INFO logger 2023-08-17 12:16:17,608 | train_utils.py:99 | Epoch 31 [Test]: loss 0.014957320910912973, mse: 0.40384766459465027, rmse: 0.6354900979516913, mae 0.5316982865333557, r2: -0.7289519402591862, nrmse: 5.352900490441139\n",
      "INFO logger 2023-08-17 12:16:17,609 | helpers.py:135 | EarlyStopping counter: 26 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,619 | train_utils.py:97 | Epoch 32 [Train]: loss 0.833295464515686, mse: 0.8310519456863403, rmse: 0.9116205053015977, mae 0.6116532683372498, r2: 0.17401541728923609, nrmse: -190.37713264323293\n",
      "INFO logger 2023-08-17 12:16:17,620 | train_utils.py:99 | Epoch 32 [Test]: loss 0.014714961802517926, mse: 0.3973039388656616, rmse: 0.6303205048748308, mae 0.5276359915733337, r2: -0.700937041096144, nrmse: 5.309355646224524\n",
      "INFO logger 2023-08-17 12:16:17,620 | helpers.py:135 | EarlyStopping counter: 27 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,633 | train_utils.py:97 | Epoch 33 [Train]: loss 0.8310519456863403, mse: 0.8288775682449341, rmse: 0.910427135055263, mae 0.611172616481781, r2: 0.1761765408338245, nrmse: -190.1279166543892\n",
      "INFO logger 2023-08-17 12:16:17,633 | train_utils.py:99 | Epoch 33 [Test]: loss 0.014444681229414764, mse: 0.3900063931941986, rmse: 0.6245049184707824, mae 0.5229349136352539, r2: -0.6696947006884142, nrmse: 5.26036943005094\n",
      "INFO logger 2023-08-17 12:16:17,634 | helpers.py:135 | EarlyStopping counter: 28 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,646 | train_utils.py:97 | Epoch 34 [Train]: loss 0.8288776278495789, mse: 0.8267720937728882, rmse: 0.909270088462657, mae 0.610755980014801, r2: 0.17826915913427321, nrmse: -189.88628627052452\n",
      "INFO logger 2023-08-17 12:16:17,646 | train_utils.py:99 | Epoch 34 [Test]: loss 0.014154073264863756, mse: 0.382159948348999, rmse: 0.6181908672481332, mae 0.5178856253623962, r2: -0.6361024975345981, nrmse: 5.2071845134089205\n",
      "INFO logger 2023-08-17 12:16:17,647 | helpers.py:135 | EarlyStopping counter: 29 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,658 | train_utils.py:97 | Epoch 35 [Train]: loss 0.8267720341682434, mse: 0.8247364163398743, rmse: 0.9081499966084206, mae 0.610403299331665, r2: 0.18029244984350157, nrmse: -189.65237328341368\n",
      "INFO logger 2023-08-17 12:16:17,658 | train_utils.py:99 | Epoch 35 [Test]: loss 0.013849928423210426, mse: 0.3739480674266815, rmse: 0.6115129331638715, mae 0.5126235485076904, r2: -0.6009458450652088, nrmse: 5.150934515572612\n",
      "INFO logger 2023-08-17 12:16:17,659 | helpers.py:135 | EarlyStopping counter: 30 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,673 | train_utils.py:97 | Epoch 36 [Train]: loss 0.8247364163398743, mse: 0.8227719664573669, rmse: 0.907067784929752, mae 0.6100896000862122, r2: 0.18224496422254366, nrmse: -189.42637095558126\n",
      "INFO logger 2023-08-17 12:16:17,674 | train_utils.py:99 | Epoch 36 [Test]: loss 0.013538146460497821, mse: 0.36552995443344116, rmse: 0.6045907330032781, mae 0.5070263743400574, r2: -0.5649062074432702, nrmse: 5.092627000232871\n",
      "INFO logger 2023-08-17 12:16:17,674 | helpers.py:135 | EarlyStopping counter: 31 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,686 | train_utils.py:97 | Epoch 37 [Train]: loss 0.8227719068527222, mse: 0.8208810091018677, rmse: 0.9060248391196941, mae 0.6098315715789795, r2: 0.1841243613638619, nrmse: -189.2085686665077\n",
      "INFO logger 2023-08-17 12:16:17,687 | train_utils.py:99 | Epoch 37 [Test]: loss 0.013223708779723556, mse: 0.357040137052536, rmse: 0.5975283566932502, mae 0.5011520981788635, r2: -0.5285595398300711, nrmse: 5.033138744262434\n",
      "INFO logger 2023-08-17 12:16:17,688 | helpers.py:135 | EarlyStopping counter: 32 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,700 | train_utils.py:97 | Epoch 38 [Train]: loss 0.8208809494972229, mse: 0.8190662860870361, rmse: 0.9050228097053886, mae 0.6096962094306946, r2: 0.18592791393385344, nrmse: -188.9993111019726\n",
      "INFO logger 2023-08-17 12:16:17,701 | train_utils.py:99 | Epoch 38 [Test]: loss 0.012910750177171495, mse: 0.348590224981308, rmse: 0.5904152987358203, mae 0.49504971504211426, r2: -0.492384007335287, nrmse: 4.973223583425802\n",
      "INFO logger 2023-08-17 12:16:17,702 | helpers.py:135 | EarlyStopping counter: 33 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,714 | train_utils.py:97 | Epoch 39 [Train]: loss 0.8190663456916809, mse: 0.817330539226532, rmse: 0.9040633491224672, mae 0.6095795035362244, r2: 0.18765324428647912, nrmse: -188.79894334631274\n",
      "INFO logger 2023-08-17 12:16:17,715 | train_utils.py:99 | Epoch 39 [Test]: loss 0.012602676947911581, mse: 0.34027227759361267, rmse: 0.5833286188707123, mae 0.48875999450683594, r2: -0.456773048727517, nrmse: 4.913530612209089\n",
      "INFO logger 2023-08-17 12:16:17,715 | helpers.py:135 | EarlyStopping counter: 34 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,725 | train_utils.py:97 | Epoch 40 [Train]: loss 0.8173304796218872, mse: 0.8156753182411194, rmse: 0.9031474509963029, mae 0.6094763278961182, r2: 0.18929833983651312, nrmse: -188.60767290204515\n",
      "INFO logger 2023-08-17 12:16:17,726 | train_utils.py:99 | Epoch 40 [Test]: loss 0.012302291614037973, mse: 0.3321618437767029, rmse: 0.57633483651147, mae 0.4823196828365326, r2: -0.42205071769144586, nrmse: 4.854620141154554\n",
      "INFO logger 2023-08-17 12:16:17,727 | helpers.py:135 | EarlyStopping counter: 35 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,736 | train_utils.py:97 | Epoch 41 [Train]: loss 0.8156753182411194, mse: 0.8141015768051147, rmse: 0.9022757764703178, mae 0.6093799471855164, r2: 0.19086248065612899, nrmse: -188.42563783823283\n",
      "INFO logger 2023-08-17 12:16:17,737 | train_utils.py:99 | Epoch 41 [Test]: loss 0.012011935313542684, mse: 0.32432225346565247, rmse: 0.5694929792944357, mae 0.476932555437088, r2: -0.38848776931529017, nrmse: 4.796989375591665\n",
      "INFO logger 2023-08-17 12:16:17,737 | helpers.py:135 | EarlyStopping counter: 36 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,747 | train_utils.py:97 | Epoch 42 [Train]: loss 0.81410151720047, mse: 0.8126087784767151, rmse: 0.9014481562889322, mae 0.6092839241027832, r2: 0.192346238389695, nrmse: -188.25280280859764\n",
      "INFO logger 2023-08-17 12:16:17,747 | train_utils.py:99 | Epoch 42 [Test]: loss 0.011733613632343433, mse: 0.3168075382709503, rmse: 0.5628565876588373, mae 0.47146257758140564, r2: -0.3563159819428783, nrmse: 4.741089300743206\n",
      "INFO logger 2023-08-17 12:16:17,748 | helpers.py:135 | EarlyStopping counter: 37 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,756 | train_utils.py:97 | Epoch 43 [Train]: loss 0.8126087188720703, mse: 0.8111947774887085, rmse: 0.9006635206827844, mae 0.6092569231987, r2: 0.19375154515928716, nrmse: -188.0889444091875\n",
      "INFO logger 2023-08-17 12:16:17,757 | train_utils.py:99 | Epoch 43 [Test]: loss 0.011469087115040532, mse: 0.30966535210609436, rmse: 0.5564758324546488, mae 0.466025173664093, r2: -0.3257388163031325, nrmse: 4.687342518894087\n",
      "INFO logger 2023-08-17 12:16:17,757 | helpers.py:135 | EarlyStopping counter: 38 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,766 | train_utils.py:97 | Epoch 44 [Train]: loss 0.8111947774887085, mse: 0.8098564743995667, rmse: 0.8999202600228349, mae 0.6093528270721436, r2: 0.19508169953192045, nrmse: -187.93372649512696\n",
      "INFO logger 2023-08-17 12:16:17,767 | train_utils.py:99 | Epoch 44 [Test]: loss 0.011219935284720527, mse: 0.30293822288513184, rmse: 0.5503982402634767, mae 0.46160489320755005, r2: -0.29693870574725856, nrmse: 4.636149358960225\n",
      "INFO logger 2023-08-17 12:16:17,767 | helpers.py:135 | EarlyStopping counter: 39 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,776 | train_utils.py:97 | Epoch 45 [Train]: loss 0.8098564743995667, mse: 0.8085895776748657, rmse: 0.8992160906449939, mae 0.6094289422035217, r2: 0.19634077022808316, nrmse: -187.7866721602706\n",
      "INFO logger 2023-08-17 12:16:17,777 | train_utils.py:99 | Epoch 45 [Test]: loss 0.010987557746745922, mse: 0.2966640591621399, rmse: 0.5446687609567303, mae 0.45717576146125793, r2: -0.2700777576826261, nrmse: 4.587888445548815\n",
      "INFO logger 2023-08-17 12:16:17,777 | helpers.py:135 | EarlyStopping counter: 40 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,789 | train_utils.py:97 | Epoch 46 [Train]: loss 0.8085896968841553, mse: 0.8073894381523132, rmse: 0.8985485174170136, mae 0.6094828844070435, r2: 0.19753363320852058, nrmse: -187.64726033678357\n",
      "INFO logger 2023-08-17 12:16:17,790 | train_utils.py:99 | Epoch 46 [Test]: loss 0.01077316094327856, mse: 0.2908753752708435, rmse: 0.5393286338317701, mae 0.4527626037597656, r2: -0.24529507114523286, nrmse: 4.542907148124428\n",
      "INFO logger 2023-08-17 12:16:17,790 | helpers.py:135 | EarlyStopping counter: 41 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,801 | train_utils.py:97 | Epoch 47 [Train]: loss 0.807389497756958, mse: 0.8062508702278137, rmse: 0.8979147343861853, mae 0.6095136404037476, r2: 0.19866532012047156, nrmse: -187.5149050470272\n",
      "INFO logger 2023-08-17 12:16:17,801 | train_utils.py:99 | Epoch 47 [Test]: loss 0.010577680887999359, mse: 0.28559738397598267, rmse: 0.5344131210739335, mae 0.44942963123321533, r2: -0.22269907171486292, nrmse: 4.501502489362627\n",
      "INFO logger 2023-08-17 12:16:17,802 | helpers.py:135 | EarlyStopping counter: 42 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,814 | train_utils.py:97 | Epoch 48 [Train]: loss 0.8062508702278137, mse: 0.8051683902740479, rmse: 0.897311757570382, mae 0.6095216274261475, r2: 0.1997410612970416, nrmse: -187.3889831348111\n",
      "INFO logger 2023-08-17 12:16:17,815 | train_utils.py:99 | Epoch 48 [Test]: loss 0.010401712523566352, mse: 0.2808462381362915, rmse: 0.5299492788336366, mae 0.4463927447795868, r2: -0.20235849382635163, nrmse: 4.463902370345268\n",
      "INFO logger 2023-08-17 12:16:17,815 | helpers.py:135 | EarlyStopping counter: 43 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,824 | train_utils.py:97 | Epoch 49 [Train]: loss 0.8051685094833374, mse: 0.8041369318962097, rmse: 0.8967368242111002, mae 0.6095079779624939, r2: 0.2007663316410978, nrmse: -187.2689176429047\n",
      "INFO logger 2023-08-17 12:16:17,825 | train_utils.py:99 | Epoch 49 [Test]: loss 0.010245434663913868, mse: 0.27662673592567444, rmse: 0.525953168947269, mae 0.4434313178062439, r2: -0.18429392264690825, nrmse: 4.43024208415113\n",
      "INFO logger 2023-08-17 12:16:17,826 | helpers.py:135 | EarlyStopping counter: 44 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,836 | train_utils.py:97 | Epoch 50 [Train]: loss 0.8041369915008545, mse: 0.8031504154205322, rmse: 0.8961865963182736, mae 0.6095420718193054, r2: 0.20174670720393584, nrmse: -187.1540114863105\n",
      "INFO logger 2023-08-17 12:16:17,836 | train_utils.py:99 | Epoch 50 [Test]: loss 0.010108561427504928, mse: 0.27293115854263306, rmse: 0.5224281372041834, mae 0.4405686557292938, r2: -0.16847247343633387, nrmse: 4.400549813245254\n",
      "INFO logger 2023-08-17 12:16:17,837 | helpers.py:135 | EarlyStopping counter: 45 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,850 | train_utils.py:97 | Epoch 51 [Train]: loss 0.8031505942344666, mse: 0.802203357219696, rmse: 0.8956580582006148, mae 0.6095789074897766, r2: 0.20268808400170713, nrmse: -187.04363488689512\n",
      "INFO logger 2023-08-17 12:16:17,850 | train_utils.py:99 | Epoch 51 [Test]: loss 0.009990326784275196, mse: 0.2697388529777527, rmse: 0.5193638926395949, mae 0.43782690167427063, r2: -0.15480549409048883, nrmse: 4.374738874120498\n",
      "INFO logger 2023-08-17 12:16:17,851 | helpers.py:135 | EarlyStopping counter: 46 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,861 | train_utils.py:97 | Epoch 52 [Train]: loss 0.802203357219696, mse: 0.8012893795967102, rmse: 0.8951476859137325, mae 0.6095958352088928, r2: 0.2035965791038472, nrmse: -186.93705192612126\n",
      "INFO logger 2023-08-17 12:16:17,862 | train_utils.py:99 | Epoch 52 [Test]: loss 0.00988951877311424, mse: 0.2670170068740845, rmse: 0.5167368836013977, mae 0.4352263808250427, r2: -0.14315268348637367, nrmse: 4.352610885007395\n",
      "INFO logger 2023-08-17 12:16:17,863 | helpers.py:135 | EarlyStopping counter: 47 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,873 | train_utils.py:97 | Epoch 53 [Train]: loss 0.8012892603874207, mse: 0.800402045249939, rmse: 0.8946519128968199, mae 0.6095940470695496, r2: 0.20447843721293313, nrmse: -186.83351778570557\n",
      "INFO logger 2023-08-17 12:16:17,873 | train_utils.py:99 | Epoch 53 [Test]: loss 0.009804543521669176, mse: 0.26472267508506775, rmse: 0.5145120747709112, mae 0.43278393149375916, r2: -0.13333029985133615, nrmse: 4.333870734187997\n",
      "INFO logger 2023-08-17 12:16:17,874 | helpers.py:135 | EarlyStopping counter: 48 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,885 | train_utils.py:97 | Epoch 54 [Train]: loss 0.800402045249939, mse: 0.7995355129241943, rmse: 0.8941674971302604, mae 0.6095748543739319, r2: 0.2053397089979202, nrmse: -186.73235542251996\n",
      "INFO logger 2023-08-17 12:16:17,885 | train_utils.py:99 | Epoch 54 [Test]: loss 0.009733549974582813, mse: 0.2628058195114136, rmse: 0.5126459007067291, mae 0.4305121600627899, r2: -0.1251238174041127, nrmse: 4.318151458473699\n",
      "INFO logger 2023-08-17 12:16:17,886 | helpers.py:135 | EarlyStopping counter: 49 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,897 | train_utils.py:97 | Epoch 55 [Train]: loss 0.7995355129241943, mse: 0.7986840605735779, rmse: 0.8936912557329728, mae 0.6095389723777771, r2: 0.20618601252460134, nrmse: -186.63290014355866\n",
      "INFO logger 2023-08-17 12:16:17,898 | train_utils.py:99 | Epoch 55 [Test]: loss 0.009674535857306587, mse: 0.2612124979496002, rmse: 0.5110895204850127, mae 0.4284881055355072, r2: -0.1183023840017603, nrmse: 4.305041657897747\n",
      "INFO logger 2023-08-17 12:16:17,899 | helpers.py:135 | EarlyStopping counter: 50 out of 50\n",
      "INFO logger 2023-08-17 12:16:17,899 | train_utils.py:117 | Early Stopping\n"
     ]
    },
    {
     "data": {
      "text/plain": "<Figure size 640x480 with 1 Axes>",
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAiMAAAGdCAYAAADAAnMpAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAA9hAAAPYQGoP6dpAABOvklEQVR4nO3deXwU9f3H8ddmk2zui9whQLjlRiAxijcKaikebam1gKC2WjzTQ2gVRK1ppbVURbFWxGp/BVE8qohiFBTlkEs5g5zhyAnkvnfn98eEhZQEkpAwOd7Px2Meu/Pdmd1PhsC++c53vmMzDMNARERExCIeVhcgIiIiHZvCiIiIiFhKYUREREQspTAiIiIillIYEREREUspjIiIiIilFEZERETEUgojIiIiYilPqwtoCJfLxZEjRwgMDMRms1ldjoiIiDSAYRgUFRURGxuLh0f9/R9tIowcOXKE+Ph4q8sQERGRJjh48CCdO3eu9/U2EUYCAwMB84cJCgqyuBoRERFpiMLCQuLj493f4/VpE2HkxKmZoKAghREREZE25mxDLDSAVURERCylMCIiIiKWUhgRERERS7WJMSMiItJ+GIZBdXU1TqfT6lLkHNntdjw9Pc952g2FEREROW8qKyvJzMyktLTU6lKkmfj5+RETE4O3t3eT36PRYeSLL75g9uzZbNiwgczMTN555x1uvPHGM+6zYsUKUlJS2LZtG/Hx8TzyyCPcfvvtTSxZRETaIpfLxb59+7Db7cTGxuLt7a2JLNswwzCorKwkNzeXffv20atXrzNObHYmjQ4jJSUlDB48mClTpnDzzTefdft9+/Zxww03cPfdd/Pvf/+btLQ07rzzTmJiYhg9enSTihYRkbansrISl8tFfHw8fn5+VpcjzcDX1xcvLy8OHDhAZWUlPj4+TXqfRoeR6667juuuu67B28+bN4+EhAT++te/AnDBBRewatUq/va3vymMiIh0QE3937O0Ts3x59nivxGrV69m1KhRtdpGjx7N6tWrW/qjRUREpA1o8QGsWVlZREVF1WqLioqisLCQsrIyfH19T9unoqKCiooK93phYWFLlykiIiIWaZV9ZampqQQHB7sX3SRPRETam27dujFnzhyry2gVWjyMREdHk52dXastOzuboKCgOntFAKZPn05BQYF7OXjwYEuXKSIiUiebzXbG5bHHHmvS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G+VVVlayYcMGpk+f7m7z8PBg1KhRrF69us59Lr74Yt544w3WrVtHYmIie/fuZenSpUyYMKHez6moqKCi4uRdNgsL678PhIiIyNnYbCd7M5rKMAxKK5014eRkSCk5Zb2k5hTSiRBz4rGkspqSCqd7m9JKJwDVp1y51Fx8vDzw9zZDjL/36WHl1PUT2/l527m0VwThjTjd1pwa9aeSl5eH0+kkKiqqVntUVBQ7d+6sc5+f/exn5OXlMXLkSAzDoLq6mrvvvpvf//739X5Oamoqs2bNakxpIiIiLcpms7l7L6LOsZPe6TJqAsqJxWk+Vp54NNuLa9pLK0881mxbeTLUFNc8Omu6bcqrXJRXVXK0YRc2ub19T3LbCCNNsWLFCp566ileeOEFkpKS2L17Nw888ABPPPEEjz76aJ37TJ8+nZSUFPd6YWEh8fHxLV2qiIjIeWH3qBlI6+PVLO9nGAYV1a5TQosZWEpremPKqswQcyLMlFX9b8hxEuZvTRCBRoaR8PBw7HY72dm1p+/Lzs4mOrrui9cfffRRJkyYwJ133gnAwIEDKSkp4Re/+AV/+MMf8PA4fdY+h8OBw2HdQREREWlLbDYbPl52fLzshPl7W11OozVq/l5vb2+GDRtWazCqy+UiLS2N5OTkOvcpLS09LXDY7XbATHIiIiLSsTX6NE1KSgqTJk1i+PDhJCYmMmfOHEpKSpg8eTIAEydOJC4ujtTUVADGjh3LM888w9ChQ92naR599FHGjh3rDiUiIiLScTU6jIwfP57c3FxmzJhBVlYWQ4YMYdmyZe5BrRkZGbV6Qh555BFsNhuPPPIIhw8fJiIigrFjx/LHP/6x+X4KERERabMaPc+IFTTPiIiISNvT0O9v3fNZRERELKUwIiIiIpZSGBERERFLKYyIiIiIpRRGRERExFIKIyIiImIphRERERGxlMKIiIiIWEphRERERCylMCIiIiKWUhgRERERSymMiIiIiKUURkRERMRSCiMiIiJiKYURERERsZTCiIiIiFhKYUREREQspTAiIiIillIYEREREUspjIiIiIilFEZERETEUgojIiIiYimFEREREbGUwoiIiIhYSmFERERELKUwIiIiIpZSGBERERFLKYyIiIiIpRRGRERExFIKIyIiImIphRERERGxlMKIiIiIWEphRERERCylMCIiIiKWalIYmTt3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sdlsREdHu5eoqKhzKlpERETaj0aFkcrKSjZs2MCoUaNOvoGHB6NGjWL16tX17ldcXEzXrl2Jj49n3LhxbNu27YyfU1FRQWFhYa1FRERE2qdGhZG8vDycTudpPRtRUVFkZWXVuU+fPn2YP38+7733Hm+88QYul4uLL76YQ4cO1fs5qampBAcHu5f4+PjGlCkiIiJtSItfTZOcnMzEiRMZMmQIl19+OUuWLCEiIoKXXnqp3n2mT59OQUGBezl48GBLlykiIiIW8WzMxuHh4djtdrKzs2u1Z2dnEx0d3aD38PLyYujQoezevbvebRwOBw6HozGliYiISBvVqJ4Rb29vhg0bRlpamrvN5XKRlpZGcnJyg97D6XSyZcsWYmJiGlepiIiItEuN6hkBSElJYdKkSQwfPpzExETmzJlDSUkJkydPBmDixInExcWRmpoKwOOPP85FF11Ez549yc/PZ/bs2Rw4cIA777yzeX8SERERaZMaHUbGjx9Pbm4uM2bMICsriyFDhrBs2TL3oNaMjAw8PE52uBw/fpy77rqLrKwsQkNDGTZsGF9//TX9+vVrvp9CRERE2iybYRiG1UWcTWFhIcHBwRQUFBAUFGR1OSIiItIADf3+1r1pRERExFIKIyIiImIphRERERGxlMKIiIiIWEphRERERCylMCIiIiKWUhgRERERSymMiIiIiKUURkRERMRSCiMiIiJiKYURERERsZTCiIiIiFhKYUREREQspTAiIiIillIYEREREUspjIiIiIilFEZERETEUgojIiIiYimFEREREbGUwoiIiIhYSmFERERELKUwIiIiIpZSGBERERFLKYyIiIiIpRRGRERExFIKIyIiImIphRERERGxlMKIiIiIWMrT6gJEpB0xDHBWgbOyZqkCwwU+weDlCzab1RWKSCukMCIiZ2YYUJILxw9Afs1y/ADkZ5jPy47XDiD1sTvALwx8Q8E3DHxDzOd+YRDSFSL6QHgf8A9XaBHpYBRGROQkw4Dj+yBjLWSshkPr4dheqC5r4hvawOYBhhOcFVCUaS5n4htqhpKI3hDe23wePQCCYptYg4i0dgojIh2ZsxqyvoOMNXBwjflYnF3HhjYzDIR0hdCuENLl5HO/cPD0Bru32fth9zKfezrAw24GnMpiKD1m9qKU1TyWHoOyfCjNg6N7IC8d8g+arx2sqedUIV2g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4XAYCxYsMLZv32784he/MEJCQoysrCyrS2v1ioqKjE2bNhmbNm0yAOOZZ54xNm3aZBw4cMAwDMP405/+ZISEhBjvvfee8d133xnjxo0zEhISjLKyMosrb33uueceIzg42FixYoWRmZnpXkpLS93b3H333UaXLl2Mzz77zFi/fr2RnJxsJCcnW1h16zRt2jRj5cqVxr59+4zvvvvOmDZtmmGz2YxPPvnEMAwdx3N16tU0hqHj2Ri//vWvjRUrVhj79u0zvvrqK2PUqFFGeHi4kZOTYxiGjqVhGEaHDSOGYRjPPfec0aVLF8Pb29tITEw01qxZY3VJbcLnn39uAKctkyZNMgzDvLz30UcfNaKiogyHw2FcffXVRnp6urVFt1J1HUfAePXVV93blJWVGb/61a+M0NBQw8/Pz7jpppuMzMxM64pupaZMmWJ07drV8Pb2NiIiIoyrr77aHUQMQ8fxXP1vGNHxbLjx48cbMTExhre3txEXF2eMHz/e2L17t/t1HUvDsBmGYVjTJyMiIiLSQceMiIiISOuhMCIiIiKWUhgRERERSymMiIiIiKUURkRERMRSCiMiIiJiKYURERERsZTCiIiIiFhKYUREREQspTAiIiIillIYEREREUspjIiIiIil/h9L3MS2X1Sy9AAAAABJRU5ErkJggg=="
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": "<Figure size 640x480 with 1 Axes>",
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAiMAAAGdCAYAAADAAnMpAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAA9hAAAPYQGoP6dpAABNBklEQVR4nO3deXwU9f3H8dfm2twJSUg2CeG+5ZQjBryNggdVKko9ESrWigfS1kJVQP1prFSKCopVAa1tRag3iiICFowiARREkDscOQjkvjbZnd8fExYiAQkkmRzv5+Mxj92Zndn97JBH8uY73/l+bYZhGIiIiIhYxMvqAkRERKRlUxgRERERSymMiIiIiKUURkRERMRSCiMiIiJiKYURERERsZTCiIiIiFhKYUREREQs5WN1AafD7XZz8OBBQkJCsNlsVpcjIiIip8EwDAoLC4mLi8PL6+TtH00ijBw8eJCEhASryxAREZEzsG/fPtq0aXPS15tEGAkJCQHMLxMaGmpxNSIiInI6CgoKSEhI8PwdP5kmEUaOXpoJDQ1VGBEREWlifqmLhTqwioiIiKUURkRERMRSCiMiIiJiqSbRZ0RERJoGwzCorKzE5XJZXYo0AG9vb3x8fM562A2FERERqRNOp5OMjAxKSkqsLkUaUGBgILGxsfj5+Z3xeyiMiIjIWXO73ezevRtvb2/i4uLw8/PTIJXNnGEYOJ1ODh06xO7du+nSpcspBzY7lVqHkS+//JIZM2aQlpZGRkYG7777Ltddd90pj1m5ciWTJk3ihx9+ICEhgUceeYQ77rjjjAoWEZHGx+l04na7SUhIIDAw0OpypIEEBATg6+vL3r17cTqd+Pv7n9H71DrCFBcX07dvX+bMmXNa++/evZurr76aSy65hI0bNzJx4kTuvPNOPv3001oXKyIijduZ/s9Ymq66+DevdcvIlVdeyZVXXnna+8+dO5cOHTrw7LPPAtCjRw9Wr17N3//+d4YNG1bbjxcREZFmpt4jbGpqKsnJydW2DRs2jNTU1Pr+aBEREWkC6j2MZGZmEhMTU21bTEwMBQUFlJaW1nhMeXk5BQUF1RYREZGmoH379syaNcvqMpqURnlxLyUlhbCwMM+iGXtFRKSu2Wy2Uy7Tp08/o/f99ttvueuuu86qtosvvthTh7+/P127diUlJQXDMDz77NmzB5vNhre3NwcOHKh2fEZGhmf8jz179ni2v/vuu5x33nmEhYUREhLCOeecw8SJEz2vL1iwoMZzcaYdU09XvYcRh8NBVlZWtW1ZWVmEhoYSEBBQ4zFTpkwhPz/fs+zbt69eavvXN3t57MMfSD+se+JFRFqajIwMzzJr1ixCQ0OrbfvjH//o2ffoYG6no3Xr1nVyR9H48ePJyMhg27ZtTJkyhalTpzJ37twT9ouPj+eNN96otu31118nPj6+2rbly5czevRorr/+etauXUtaWhpPPvkkFRUV1fb7+XnIyMhg7969Z/19TqXew0hSUhLLly+vtm3ZsmUkJSWd9Bi73e6Zobe+ZuqtdLl5aeVO5q/Zw8V/W8Hd/0xj3Z4j1VKniIicGcMwKHFWWrKc7u9xh8PhWcLCwrDZbJ71rVu3EhISwieffMKAAQOw2+2sXr2anTt3cu211xITE0NwcDCDBg3i888/r/a+P79MY7PZePXVVxk5ciSBgYF06dKFDz744BfrCwwMxOFw0K5dO8aOHUufPn1YtmzZCfuNGTOG+fPnV9s2f/58xowZU23bhx9+yNChQ/nTn/5Et27d6Nq1K9ddd90Jd8cefx6OLj/vblHXan03TVFRETt27PCs7969m40bNxIREUHbtm2ZMmUKBw4c8KS0u+++m9mzZ/PQQw8xbtw4vvjiC95++22WLFlSd9/iDHh72XhqZG9eXb2bL386xNIfMln6QyZ9E8L57fkduLKXA1/vRnkVS0Sk0SutcNFzqjVDOGx5fBiBfnUzpufkyZP529/+RseOHWnVqhX79u3jqquu4sknn8Rut/PGG28wYsQItm3bRtu2bU/6Po899hjPPPMMM2bM4IUXXuCWW25h7969RERE/GINhmGwevVqtm7dSpcuXU54/Ve/+hVz585l9erVnH/++axevZrc3FxGjBjBE0884dnP4XDw73//m82bN9OrV68zOyH1pNZ/bdetW0f//v3p378/AJMmTaJ///5MnToVMJu90tPTPft36NCBJUuWsGzZMvr27cuzzz7Lq6++avltvTabjQu7tuaNcYP5dOKFjB6YgJ+PF9/ty+P+/2zgomdW8PKqneSXVvzym4mISLP0+OOPc/nll9OpUyciIiLo27cvv/vd7+jVqxddunThiSeeoFOnTr/Y0nHHHXdw00030blzZ5566imKiopYu3btKY958cUX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MCIiIiKWUhgRERERSymMiIiIiKUURkRERMRSCiMiIiJiKYURERERsZTCiIiIiFhKYUREREQspTAiIiIillIYEREREUspjIiIiIilFEZERETEUgojIiIiYimFEREREbGUwoiIiIhYSmFERERELKUwIiIiIpZSGBERERFLKYyIiIiIpRRGRERExFIKIyIiImIphRERERGxlMKIiIiIWEphRERERCylMCIiIiKWUhgRERERSymMiIiIiKUURkRERMRSCiMiIiJiKYURERERsZTCiIiIiFhKYUREREQspTAiIiIillIYEREREUspjIiIiIilFEZERETEUgojIiIiYimFEREREbGUwoiIiIhYSmFERERELHVGYWTOnDm0b98ef39/EhMTWbt27Sn3nzVrFt26dSMgIICEhAQefPBBysrKzqhgERERaV5qHUYWLlzIpEmTmDZtGuvXr6dv374MGzaM7OzsGvf/97//zeTJk5k2bRo//vgjr732GgsXLuQvf/nLWRcvIiIiTV+tw8jMmTMZP348Y8eOpWfPnsydO5fAwEDmzZtX4/5fffUVQ4cO5eabb6Z9+/ZcccUV3HTTTb/YmiIiIiItQ63CiNPpJC0tjeTk5GNv4OVFcnIyqampNR4zZMgQ0tLSPOFj165dfPzxx1x11VUn/Zzy8nIKCgqqLSIiItI8+dRm55ycHFwuFzExMdW2x8TEsHXr1hqPufnmm8nJyeH888/HMAwqKyu5++67T3mZJiUlhccee6w2pYmIiEgTVe9306xcuZKnnnqKF198kfXr1/POO++wZMkSnnjiiZMeM2XKFPLz8z3Lvn376rtMERERsUitWkaioqLw9vYmKyur2vasrCwcDkeNxzz66KPcdttt3HnnnQD07t2b4uJi7rrrLh5++GG8vE7MQ3a7HbvdXpvSREREpImqVcuIn58fAwYMYPny5Z5tbreb5cuXk5SUVOMxJSUlJwQOb29vAAzDqG29IiIi0szUqmUEYNKkSYwZM4aBAwcyePBgZs2aRXFxMWPHjgXg9ttvJz4+npSUFABGjBjBzJkz6d+/P4mJiezYsYNHH32UESNGeEKJiIiItFy1DiOjR4/m0KFDTJ06lczMTPr168fSpUs9nVrT09OrtYQ88sgj2Gw2HnnkEQ4cOEDr1q0ZMWIETz75ZN19CxEREWmybEYTuFZSUFBAWFgY+fn5hIaGWl2OiIiInIbT/futuWlERETEUgojIiIiYimFEREREbGUwoiIiIhYSmFERERELKUwIiIiIpZSGBERERFLKYyIiIiIpRRGRERExFIKIyIiImIphRERERGxlMKIiIiIWEphRERERCylMCIiIiKWUhgRERERSymMiIiIiKUURkRERMRSCiMiIiJiKYURERERsZTCiIiIiFhKYUREREQspTAiIiIillIYEREREUspjIiIiIilFEZERETEUgojIiIiYimFEREREbGUwoiIiIhYSmFERERELKUwIiIiIpZSGBERERFLKYyIiIiIpRRGRERExFIKIyIiImIphRERERGxlMKIiIiIWEphRERERCylMCIiIiKWUhgRERERSymMiIiIiKUURkRERMRSCiMiIiJiKYURERERsZTCiIiIiFhKYUREREQspTAiIiIillIYEREREUspjIiIiIilFEZERETEUgojIiIiYimFEREREbGUwoiIiIhYSmFERERELKUwIiIiIpZSGBERERFLKYyIiIiIpc4ojMyZM4f27dvj7+9PYmIia9euPem+F198MTab7YTl6quvPuOiRUREpPmodRhZuHAhkyZNYtq0aaxfv56+ffsybNgwsrOza9z/nXfeISMjw7Ns3rwZb29vbrjhhrMuXkRERJq+WoeRmTNnMn78eMaOHUvPnj2ZO3cugYGBzJs3r8b9IyIicDgcnmXZsmUEBgYqjIiIiAhQyzDidDpJS0sjOTn52Bt4eZGcnExqauppvcdrr73Gb37zG4KCgk66T3l5OQUFBdUWERERaZ5qFUZycnJwuVzExMRU2x4TE0NmZuYvHr927Vo2b97MnXfeecr9UlJSCAsL8ywJCQm1KVNERESakAa9m+a1116jd+/eDB48+JT7TZkyhfz8fM+yb9++BqpQREREGppPbXaOiorC29ubrKysatuzsrJwOBynPLa4uJi33nqLxx9//Bc/x263Y7fba1OaiIiINFG1ahnx8/NjwIABLF++3LPN7XazfPlykpKSTnnsokWLKC8v59Zbbz2zSkVERKRZqlXLCMCkSZMYM2YMAwcOZPDgwcyaNYvi4mLGjh0LwO233058fDwpKSnVjnvttde47rrriIyMrJvKRUREpFmodRgZPXo0hw4dYurUqWRmZtKvXz+WLl3q6dSanp6Ol1f1Bpdt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"
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO logger 2023-08-17 12:16:18,079 | train_utils.py:140 | Best Loss: 0.009219224806185122, Best epoch: 55\n"
     ]
    }
   ],
   "source": [
    "trained_model = fit(model, X_train, y_train, X_val, y_val)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "outputs": [],
   "source": [],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2023-08-17T12:16:18.087031Z",
     "end_time": "2023-08-17T12:16:18.104033Z"
    }
   }
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3.9.10 64-bit",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.10"
  },
  "vscode": {
   "interpreter": {
    "hash": "a39106e1a9d6d153b7400628e7589ff266b5caee5b0db427f0903be982155882"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
